﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
//TODO:  Use two media elements in ping-pong mode. Then one ends the second should be primed (pre-buffered) and ready to play.

/*
 *   Usage:
 *   private Sound sound;
 *   sound = new Sound("Ignition_rev.mp3", 400, 300, 6, false);
 *   sound.Loop(true);
 *   LayoutRoot.Children.Add(sound.getMediaElement());
 *   sound.PlaySound();
 */
namespace ManPowerEngine
{
    public class Sound
    {
        private MediaElement mMediaElement;
		private MediaElement mMediaElementBackup;
		private string mURI;
		private bool mLoop = false;
		private bool mUsingBackup = false;
		DispatcherTimer mTimer;
		
		//TimeSpan offset = TimeSpan.FromMilliseconds(500);

		/// <summary>
		/// initialize a Sound renderer
		/// </summary>
		/// <param name="uri">URI of this Sound</param>
		/// <param name="loop">is this a loop sound?</param>
		/// <param name="autoplay">Start to play after load?</param>
		internal Sound(string uri, bool loop, bool autoplay)			
		{
			mURI = uri;
            mMediaElement = new MediaElement();
			{
				mMediaElement.Height = 1;
				mMediaElement.Width = 1;
			}
			Loop = loop;
			if (mLoop)
			{
				mMediaElementBackup = new MediaElement();
				{
					mMediaElementBackup.Height = 1;
					mMediaElementBackup.Width = 1;
				}
				mMediaElementBackup.MediaEnded += new RoutedEventHandler(mMediaElement_MediaEnded);
				RenderSystem.Canvas.Children.Add(mMediaElementBackup);
			}
			mMediaElement.MediaOpened += new RoutedEventHandler(mMediaElement_MediaOpened);
			mMediaElement.MediaEnded += new RoutedEventHandler(mMediaElement_MediaEnded);
			mMediaElement.AutoPlay = autoplay;
			mMediaElement.Source = new Uri(uri, UriKind.Relative);
			RenderSystem.Canvas.Children.Add(mMediaElement);
		}

		void mMediaElement_MediaEnded(object sender, RoutedEventArgs e)
		{
			(sender as MediaElement).Position = TimeSpan.Zero;
		}

		void mMediaElement_MediaOpened(object sender, RoutedEventArgs e)
		{
			if (mLoop)
			{
				Duration len = mMediaElement.NaturalDuration;
				mTimer = new DispatcherTimer();
				mTimer.Interval = len.TimeSpan - TimeSpan.FromMilliseconds(140);

				mTimer.Tick += new EventHandler(mTimer_Tick);
				mTimer.Start();
				mMediaElementBackup.Source = mMediaElement.Source;
			}
		}

		void mTimer_Tick(object sender, EventArgs e)
		{
			mUsingBackup = !mUsingBackup;
			if (mUsingBackup)
			{
				mMediaElementBackup.Play();
			}
			else
			{
				mMediaElement.Play();
			}
		}

		/// <summary>
		/// URI of this Sound
		/// </summary>
		public string URI
		{
			get
			{
				return mURI;
			}
		}

		internal void CleanUp()
		{
			if (mMediaElement != null)
			{
				mMediaElement.Stop();
				RenderSystem.Canvas.Children.Remove(mMediaElement);
				mMediaElement = null;
			}
		}

		/// <summary>
		/// Is this sound being played in a loop?
		/// </summary>
		public bool Loop
		{
			get
			{
				return mLoop;
			}
			set
			{
				if (mLoop == value)
					return;
				mLoop = value;
			}
		}

        /// <summary>
        /// Play sound 
        /// </summary>
        public void Play()
        {
            mMediaElement.Play();
        }
        /// <summary>
        /// Stop sound
        /// </summary>
        public void Stop()
        {
            mMediaElement.Stop();
        }
        /// <summary>
        /// Pause sound
        /// </summary>
        public void Pause()
        {
            mMediaElement.Pause();
        }
        /// <summary>
        /// Set volume of the sound
        /// </summary>
        /// <param name="volume">Give floating point number for setting sound</param>
        public double Volume
        {
			get
			{
				return mMediaElement.Volume;
			}
			set
			{
				mMediaElement.Volume = value;
			}
           
        }
    }
}
